package model;
import view.*;
import javax.swing.*;

import controller.*;

import java.net.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;


public class GameClient extends JFrame {

	private Socket socket;

	private static final int PORTNUM = 10055;
	private static final String ADDRESS = "localhost";

	private PrintWriter outputToServer;
	private BufferedReader inputFromServer;

	private boolean isConnected = false;
	private boolean gameStarted = false;

	private ClientGameBoard cgb = new ClientGameBoard(this);

	private ClientPlayer cP;

	private FileMenu filemenu = new FileMenu(this);

	private int start = 0;

	public ClientPlayer getCP(){
		return cP;
	}

	public void setCP(int xCoord, int yCoord){
		cP = new ClientPlayer(true, xCoord, yCoord);
	}

	public static void main(String args[]) {
		new GameClient();
	}

	/*		Sending numbers to the server
	 * 		
	 * 		+-------------+------------------------------------------------+
	 *  	| NUMBER SENT | WHAT IT MEANS								   |
	 *  	+-------------+------------------------------------------------+
	 * 		| 1, 2, 3, 4  | Top Left, Top Right, Bottom Left, Bottom Right |
	 * 		| 5			  | Create a game								   |
	 * 		| 6			  | Queue for a game							   |
	 * 		+-------------+------------------------------------------------+
	 */

	public GameClient() 
	{
		setLayout(new BorderLayout());
		setJMenuBar(filemenu);

		add(cgb, BorderLayout.CENTER);
		addKeyListener(new KeyboardListener(this));

		setSize(800,820);
		setTitle("********** Monster Munchies **********");
		setResizable(false);
		setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		setVisible(true);
		setLocationRelativeTo(null);

		/* JOptionPane.showMessageDialog(getContentPane(), "1. Connect to the Game Server from the Menu\n" +
				"2. Select Create game to start playing!","Welcome to Monster Munchies!",JOptionPane.INFORMATION_MESSAGE);*/

		this.addWindowListener(new WindowAdapter(){
			public void windowClosing(WindowEvent e){
				promptClose();
			}
		});
	}

	public void actionPerformed(ActionEvent e)
	{
		String actionCommand = e.getActionCommand();
	}

	public void promptClose(){
		int response = JOptionPane.showConfirmDialog(null, "Do you want to exit?","Exit Program??",JOptionPane.YES_NO_OPTION);
		if (response == JOptionPane.YES_OPTION){
			System.exit(0);
		}
	}

	public PrintWriter getOutputToServer() {
		return outputToServer;
	}

	public void setOutputToServer(PrintWriter outputToServer) {
		this.outputToServer = outputToServer;
	}

	public BufferedReader getInputFromServer() {
		return inputFromServer;
	}

	public void setInputFromServer(BufferedReader inputFromServer) {
		this.inputFromServer = inputFromServer;
	}

	public int getPortNum(){
		return PORTNUM;
	}

	public String getAddress(){
		return ADDRESS;
	}

	public boolean isStarted(){
		return gameStarted;
	}

	public boolean checkConnected(){
		return isConnected;
	}

	public void setConnected(){
		isConnected = true;
	}

	public Socket getSocket(){
		return socket;
	}

	public int getStart(){
		return start;
	}

	public void setStart(int start){
		this.start = start;
	}

	public ClientGameBoard getCGB(){
		return cgb;
	}

	public synchronized void createSocket(){
		try {
			this.socket = new Socket(ADDRESS, PORTNUM);
		} catch (ConnectException ex) {
			// Connect Exception will happen here
			// System.out.println("Connection refused, please check your local network settings");
			JOptionPane.showMessageDialog(getContentPane(), "Failed to connect to server.\nPlease " +
					"check your local network settings","Connection Error",JOptionPane.ERROR_MESSAGE);
		} catch (IOException e) {
			System.out.println("IO exception occured. Please review");
		} catch (Exception e) {
			System.out.println("Normal exception occured. Please review");
		} 
	}

	public void chooseSide(){
		boolean sideChosen = false;
		try{
			int sent = 0;
			do{
				/*	A dialog box will appear with 4 options to choose from.
				 * 	Each will correspond to the side where the user will start from
				 */
				System.out.println("CHOOSING SIDE");
				Object[] possibilities = {"1", "2", "3", "4" };
				Object[] options = { "OK", "CANCEL" };
				String s = (String)JOptionPane.showInputDialog(this, "1 = Top Left, 2 = Top Right\n3 = Bottom Left, 4 = Bottom Right", "Pick a Side", JOptionPane.PLAIN_MESSAGE,
						null, possibilities, "Top Left");

				// Send chosen side to the server (Change Strings to Integers)
				int sentNumber = Integer.parseInt(s);

				getOutputToServer().write(sentNumber);
				getOutputToServer().flush();

				// Get input from the Server side, reads the int that is returned
				int choose = getInputFromServer().read();
				
				// 0 from the server means OK, your spot is reserved
				//if (inInt == 0){
				if (choose == 1){
					JOptionPane.showMessageDialog(getContentPane(), "Your side has been selected!\nPlease wait for other players","Side Selected",JOptionPane.INFORMATION_MESSAGE);
					sideChosen = true;
					sent = sentNumber;
				}
				else{
					JOptionPane.showMessageDialog(getContentPane(), "This side has been taken\nPlease " +
							"pick another side","Side has been taken",JOptionPane.ERROR_MESSAGE);
				}
			} while (sideChosen == false);
			System.out.println("A side has been chosen, " + sent);
			gameStarted = true;
			setStart(sent);
			updateBoard();
		}
		catch(Exception ex){
			System.out.println("Exception while choosing side occured. Please review");
		}
	}

	public void updateBoard(){

		try{
			this.getCGB().removeAll();
			this.getCGB().setStage();
			this.getCGB().validate();
			this.getCGB().repaint();

			System.out.println("The Board has been updated");
		}
		catch(Exception ex){
			ex.printStackTrace();
		}

	}

	public void startGame(){
		// Refresh game board, with all players and server generates a monster in the middle
		// Makes sure that the server creates a monster

		try{
			//			do{
			//				client constantly updates the board with updateBoard()
			//			}while (server is running);

			// while (true){
			// do all the concurrency stuff, includes board updating
			// }

		}
		catch(Exception ex){
			// TODO Auto-generated catch block
			System.out.println("Exception in Start Game method occured. Please review");
		}
	}

	public boolean move(int movement){
		try{
			// Send tile to move to, to the server
			int moveInteger[] = {7,8,9,10};

			// Server interprets 7 as Up, 8 as Down, 9 as Left, 10 as Right
			getOutputToServer().write(moveInteger[movement]);
			getOutputToServer().flush();

			// Get input from the Server side, reads the int that is returned
			//int inInt = getInputFromServer().readInt();
			int move = getInputFromServer().read();

			// 0 from the server means OK, your spot is reserved
			//if (inInt == 0){
			if (move == 1){

				int moveUp = 0;
				int moveLeft = 0;

				if (moveInteger[movement] == 7){
					moveUp = -1;
				}
				else if (moveInteger[movement] == 8){
					moveUp = 1;
				}
				else if (moveInteger[movement] == 9){
					moveLeft = -1;
				}
				else {
					moveLeft = 1;
				}
				
				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX()+moveUp,cP.getPosY()+moveLeft);
				this.getCGB().validate();
				this.getCGB().repaint();
			}
			else{
				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX(),cP.getPosY());
				this.getCGB().validate();
				this.getCGB().repaint();

			}
			System.out.println("The Board has been updated with movement");
			return true;
		}
		catch(Exception ex){
			ex.printStackTrace();
			System.out.println("Error with moving");
		}
		return false;
	}
	
	public boolean teleport(){
		try{
			// Tells server I want to teleport to [4,4]
			getOutputToServer().write(11);
			getOutputToServer().flush();

			int allowTeleport = getInputFromServer().read();

			if (allowTeleport == 1){
				this.getCGB().removeAll();
				this.getCGB().refreshStage(4,4);
				this.getCGB().validate();
				this.getCGB().repaint();

				System.out.println("Your Teleport has been granted");
			}
			else if(allowTeleport == 2){
				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX(),cP.getPosY());
				this.getCGB().validate();
				this.getCGB().repaint();
				System.out.println("Teleport Refused: Another player is at 4:4");
			}
			else{
				this.getCGB().removeAll();
				this.getCGB().refreshStage(cP.getPosX(),cP.getPosY());
				this.getCGB().validate();
				this.getCGB().repaint();
				System.out.println("Teleport Refused: You have ran out of teleports");
			}
			
			return true;
		}
		catch(Exception ex){
			ex.printStackTrace();
			System.out.println("Error with teleporting");
		}
		return false;
	}
}
